# Simple script to generate binders between matlab and eyelink libraries. It 
# supports only linux on ubuntu.

import os.path
from distutils import ccompiler


#open_eyelink = binder('mex_open_eyelink')
#open_eyelink.compile()


    
class binder:
    '''A Simple class that implements creation of the mex files.'''
 
    compiler = 'gcc'
    # .o files to bind
    bindo = []
    libsL = ['/usr/local/MATLAB/R2012b/bin/glnxa64','/usr/lib']
    libsl = ['eyelink_core','mx','mex','mat','m','stdc++','eyelink_core_graphics',\
    'sdl_util `sdl-config --libs`','SDL_image','SDL_mixer','rt']
    include =  ['/usr/include','/usr/local/MATLAB/R2012b/extern/include','/usr/local/MATLAB/R2012b/simulink/include']
    oflags = ['-v','`sdl-config --cflags`','-DMATLAB_MEX_FILE','-ansi', \
    '-D_GNU_SOURCE','-fexceptions','-fPIC','-fno-omit-frame-pointer',\
    '-pthread','-DMX_COMPAT_32','-O','-DNDEBUG']
    mxflags = ['-O','-pthread','-shared','-Wl,--version-script,/usr/local/MATLAB/R2012b/extern/lib/glnxa64/mexFunction.map',\
    '-Wl,--no-undefined']
    # Command to create o file.
    _ofile = ''
    # Command to link the o file and generate file. 
    _mxfile = ''
    # This needs to be done properly...
    def __init__(self,filename):
        self.filename = filename
    def _wofile(self):
    		self._ofile = [self.compiler,'-c'] + ['-I{0}'.format(i) for i in self.include] + \
      self.oflags + ['{0}.c'.format(self.filename),'-o',\
      '{0}.o'.format(self.filename)]
      
    def _wmxfile(self):
    		self._mxfile = [self.compiler] + self.mxflags + ['{0}.o'.format(self.filename)] + \
      self.bindo + ['-Wl,-rpath-link,/usr/local/MATLAB/R2012b/bin/glnxa64'] +\
      ['-L{0}'.format(i) for i in self.libsL] + ['-l{0}'.format(i) for i in self.libsl ] + \
      ['-o', '"{0}.mexa64"'.format(self.filename)]
    
    def compile(self,silent=0):
        self._wofile()
        self._wmxfile()
        s = ''
        for i in self._ofile: s += '{0} '.format(i)
        print(s)
        s = ''
        for i in self._mxfile: s += '{0} '.format(i)
        print(s)
        
    def write_sh(self,loc='./'):
        target = os.path.join(loc,'{0}.sh'.format(self.filename))
        with open(target,'w') as shfile:
             shfile.write('\n'.join(['#!/bin/sh -f',\
             ' '.join(self._ofile),\
             ' '.join(self._mxfile)]))
        return target
    def ocompile(self):
        cc = ccompiler.new_compiler(verbose=1)
        cc.compile(['{0}.c'.format(self.filename)],include_dirs=self.include,\
        extra_preargs=self.oflags)
        
        

class mx_c:
    ''' This class is used to embed c code in a py file to avoid having noise
    in the directories.'''

    #Documentation for an aothomatically produced m file.'''

    mdoc = ''
    macros = ''
    code = ''
    
    # Lists

    mcopyright = [\
'''%----------------------------------------------------------------------------
% Copyright Eduardo Aponte 2013
% aponteeduardo@gmail.com''']
    preamble = [\
    '''/*
 * Copyright Eduardo Aponte 2013
 * aponteeduardo@gmail.com
 */''']
    headers = []
    _output = []
    def O_mx_file(self,silent=0,target=None):
        ''' Creates a temporary file to compile. '''
        # Produce a list with the elements
        self._output += self.preamble + \
        ['\n'.join(['#include {0}'.format(i) for i in self.headers]),\
         self.macros,\
         self.code]
        if not silent:
             print('\n'.join(self._output))        
        if target:
            target.write('\n'.join(self._output))
    def O_m_file (self,silent=0,target=None):
        ''' Creates a m file for documentation porpuses.'''
        if not silent:
             print(self.mdoc + self.mcopyright[0])        
        if target:
            target.write(self.mdoc + self.mcopyright[0])
        
    
class binder_py(binder):
    '''Like binder but from py embedded code. '''
    def __init__(self,filename):
           binder.__init__(self, filename)
           self.mx_c = mx_c()
    def write_c(self,loc='./'):
        target = os.path.join(loc,'{0}.c'.format(self.filename))
        with open(target,'w') as cfile:
            self.mx_c.O_mx_file(target=cfile)
        return target
    def write_m(self,loc='./'):
        target = os.path.join(loc,'{0}.m'.format(self.filename))
        with open(target,'w') as mfile:
            self.mx_c.O_m_file(target=mfile)
        return target
